import 'dart:async';
import 'dart:collection';
import 'dart:math';
import 'dart:typed_data';
import 'dart:ui' as ui;
import 'package:huxiaodui/api/model/alarm_model.dart';
import 'package:huxiaodui/api/model/mobile_app_model.dart';
import 'package:huxiaodui/utils/global_controller.dart';
import 'package:huxiaodui/main.dart';
import 'package:huxiaodui/components/alarm_marker.dart';
import 'package:amap_flutter_map/amap_flutter_map.dart';
import 'package:amap_flutter_base/amap_flutter_base.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:flutter/rendering.dart';
import 'package:flutter/widgets.dart';
import 'package:screenshot/screenshot.dart';

class MapController extends ChangeNotifier {
  static final MapController _instance = MapController._internal();
  factory MapController() {
    return _instance;
  }
  MapController._internal();

  ///标记-用户列表
  List<MobileAppModel> mobileApps = [];

  ///标记-警报列表
  List<AlarmModel> alarms = [];

  ///展示地图标记点数据
  Widget? showMarkerInfo;

  ///地图控制器
  AMapController? mapController;

  ///当前高度
  double currZoom = 15;

  ///当前经纬度
  LatLng? currLatLng;

  Set<Marker> markers = HashSet();

  void refresh() {
    notifyListeners();
  }

  static Future<Uint8List?> widgetToImage({
    required Widget widget,
    double width = 1000,
    double height = 1000,
    double pixelRatio = 1.0,
    Alignment alignment = Alignment.bottomCenter,
  }) async {
    try {
      final controller = ScreenshotController();
      return await controller.captureFromWidget(
        Container(
          alignment: alignment,
          color: Colors.transparent,
          width: width,
          height: height,
          child: widget,
        ),
        pixelRatio: pixelRatio,
        delay: const Duration(milliseconds: 100),
      );
    } catch (e, stack) {
      debugPrint("widgetToImage failed: $e");
      return null;
    }
  }


  Future<Widget> getMarker(
      {required String text,
      required String path,
      required double height}) async {
    AssetImage provider = AssetImage(path);

    await precacheImage(provider, navigatorKey.currentState!.context);
    return SizedBox(
      height: height,
      child: Column(
        mainAxisAlignment: MainAxisAlignment.spaceBetween,
        children: [
          Container(
            padding: const EdgeInsets.all(10),
            decoration: BoxDecoration(
              color: Colors.white,
              borderRadius: BorderRadius.circular(30),
              border: Border.all(
                color: Colors.black,
                width: 2.0,
              ),
            ),
            child: Directionality(
              textDirection: TextDirection.ltr,
              child: Text(
                text,
                style: const TextStyle(
                  fontWeight: FontWeight.normal,
                  fontSize: 31,
                  color: Colors.black,
                ),
              ),
            ),
          ),
          Image(
            image: provider,
          ),
        ],
      ),
    );
  }

  Future<void> updateMarkers() async {

    Set<Marker> newMarkers = HashSet();
    List<AlarmModel> alarms1 = [];
    alarms1.addAll(alarms);
    for (var value in alarms1) {
      if (value.expired) continue;

      if (value.unit.latLng != null &&
          value.unit.latLng?.latitude != null &&
          value.unit.latLng?.longitude != null) {
        Widget widget = await getMarker(
            text: value.unit.name,
            path: 'assets/images/location/unit.png',
            height: 200);
        Uint8List? bd = await widgetToImage(widget: widget);
        if (bd != null && bd.isNotEmpty) {
          newMarkers.add(Marker(
            // infoWindow: InfoWindow(title: value.unit.name),
            infoWindowEnable: false,
            position: value.unit.latLng!,
            zIndex: 2,
            icon: BitmapDescriptor.fromBytes(bd),
            onTap: (val) => MapController().toMarker(value),
          ));
        }
      }
      if (value.latLng != null &&
          (value.latLng?.latitude != null && value.latLng?.longitude != null)) {
        Widget widget = await getMarker(
            text: value.unit.name,
            path: 'assets/images/location/alarm.png',
            height: 200);
        Uint8List? bd = await widgetToImage(widget: widget);
        if (bd != null && bd.isNotEmpty) {
          newMarkers.add(Marker(
            infoWindowEnable: false,
            position: value.latLng!,
            zIndex: 3,
            icon: BitmapDescriptor.fromBytes(bd),
            onTap: (val) => MapController().toMarker(value),
          ));
        }
      }
    }

    for (var value in mobileApps) {
      if (value.latLng == null || value.id == GlobalController().user?.id) continue;
      if ( value.latLng?.latitude == null || value.latLng?.longitude == null) continue;

      Widget widget = await getMarker(
          text: value.name,
          path: 'assets/images/location/user.png',
          height: 140);
      Uint8List? bd = await widgetToImage(widget: widget);
      if (bd != null && bd.isNotEmpty) {
        newMarkers.add(Marker(
          infoWindowEnable: false,
          position: value.latLng!,
          zIndex: 1,
          icon: BitmapDescriptor.fromBytes(bd),
          onTap: (val) {
            MapController().moveMap(latLng: value.latLng!);
          },
        ));
      }
    }

    if (MapController().currLatLng != null &&
        MapController().currLatLng?.latitude != null &&
        MapController().currLatLng?.longitude != null) {
      if (GlobalController().user != null) {
        Widget widget = await getMarker(
            text: GlobalController().user!.name,
            path: 'assets/images/location/my.png',
            height: 130);
        Uint8List? bd = await widgetToImage(widget: widget);
        if (bd != null && bd.isNotEmpty) {
          newMarkers.add(Marker(
            infoWindowEnable: false,
            position: MapController().currLatLng!,
            zIndex: 1,
            icon: BitmapDescriptor.fromBytes(bd),
            onTap: (val) {
              MapController().moveMap(latLng: MapController().currLatLng!);
            },
          ));
        }
      } else {
        newMarkers.add(Marker(
          infoWindowEnable: false,
          position: MapController().currLatLng!,
          zIndex: 1,
          icon: BitmapDescriptor.fromIconPath("assets/images/location/my.png"),
          onTap: (val) {
            MapController().moveMap(latLng: MapController().currLatLng!);
          },
        ));
      }
    }

    markers = newMarkers;

    notifyListeners();
  }

  void toMarker(AlarmModel alarm) {
    GlobalController.toFirst(showDrawer: false);
    showMarkerInfo = AlarmMarker(alarm: alarm);
    MapController().moveMap(latLng: alarm.latLng!);
    notifyListeners();
  }

  void showMarker(AlarmModel alarm) {
    showMarkerInfo = AlarmMarker(alarm: alarm);
    notifyListeners();
  }

  void hideMarkerInfo() {
    showMarkerInfo = null;
    notifyListeners();
  }

  ///移动地图到某个点
  void moveMap({required LatLng latLng, double? zoom}) {
    if (mapController == null) {
      return;
    }

    mapController?.moveCamera(
      CameraUpdate.newCameraPosition(
        CameraPosition(
          target: latLng,
          zoom: zoom ?? currZoom,
        ),
      ),
    );

    notifyListeners();
  }

  void moveCenter(LatLng latLng) {
    if (currLatLng != null) {
      var center = LatLng(
        (currLatLng!.latitude + latLng.latitude) / 2,
        (currLatLng!.longitude + latLng.longitude) / 2,
      );
      var zoom = _calculateZoomLevel(currLatLng!, latLng);
      MapController().moveMap(latLng: center, zoom: zoom);
    } else {
      MapController().moveMap(latLng: latLng);
    }
    notifyListeners();
  }

  AlarmModel? getAlarm(int id) {
    for (var value in MapController().alarms) {
      if (value.id == id) return value;
    }

    return null;
  }

  MobileAppModel? getMobileApp(int id) {
    for (var value in MapController().mobileApps) {
      if (value.id == id) return value;
    }
    return null;
  }

  double _calculateZoomLevel(LatLng point1, LatLng point2) {
    Size screenSize = MediaQuery.of(navigatorKey.currentState!.context).size;
    final double minLatitude =
        point1.latitude < point2.latitude ? point1.latitude : point2.latitude;
    final double maxLatitude =
        point1.latitude > point2.latitude ? point1.latitude : point2.latitude;
    final double minLongitude = point1.longitude < point2.longitude
        ? point1.longitude
        : point2.longitude;
    final double maxLongitude = point1.longitude > point2.longitude
        ? point1.longitude
        : point2.longitude;

    final double longitudeDelta = maxLongitude - minLongitude;
    final double latitudeDelta = maxLatitude - minLatitude;

    final double horizontalZoom =
        _calculateZoomLevelByDelta(longitudeDelta, screenSize.width);
    final double verticalZoom =
        _calculateZoomLevelByDelta(latitudeDelta, screenSize.height);

    return horizontalZoom < verticalZoom ? horizontalZoom : verticalZoom;
  }

  double _calculateZoomLevelByDelta(double delta, double dimension) {
    const double zoomFactor = 1.3; // 调整因子，可以根据需求调整

    final double zoomLevel = (log(dimension / (delta * zoomFactor))) / log(2);
    return zoomLevel;
  }
}
